#ifndef _SCENENODE_HPP
#define _SCENENODE_HPP

#include "Maths.hpp"

#include <list>

class SceneNode;
typedef std::list<SceneNode*> SceneNodeCollection;
typedef SceneNodeCollection::iterator SceneNodeIter;

class SceneNode
{
	SceneNode*          m_parent;
	SceneNodeCollection m_children;
	Xform               m_xform;
	//Mesh                m_mesh;
	
	void addChild(SceneNode* child)
	{
		m_children.push_back(this);
	}
	void removeChild(SceneNode* child)
	{
		// Note: This is not available for std::vector
		m_children.remove(child);
	}

	// No copying or assignment
	// Note: These could be implemented if necessary
	SceneNode(const SceneNode& other);
	SceneNode& operator = (const SceneNode& other);
public:
	SceneNode() : m_parent(0) {}
	SceneNode(SceneNode* parent) { attachTo(parent); }
	virtual ~SceneNode()
	{
		m_parent->removeChild(this);
	}
	
	inline const SceneNode* getParent() const             { return m_parent; }
	inline SceneNode* getParent()                         { return m_parent; }
	inline SceneNodeCollection& getChildren()             { return m_children; }
	inline const SceneNodeCollection& getChildren() const { return m_children; }
	inline bool isLeaf() const                    { return m_children.empty(); }
	
	void attachTo(SceneNode* parent)
	{
		m_parent = parent;
		parent->addChild(this);
	}
	
	inline const Xform& getXform() const { return m_xform; }
	inline Xform&       getXform()       { return m_xform; }
	inline void         setXform(const Xform& xform)
	{ m_xform = xform; }
	
	inline const Vector& getPos() const      { return m_xform.getPos(); }
	inline Vector&       getPos()            { return m_xform.getPos(); }
	inline void          setPos(const Vector& pos)
	{ m_xform.setPos(pos); }
	
	inline const Orientation& getOri() const { return m_xform.getOri(); }
	inline Orientation&       getOri()       { return m_xform.getOri(); }
	inline void               setOri(const Orientation& ori)
	{ m_xform.setOri(ori); }
	
	const AABB& getAABB() const;
};

#endif //_SCENENODE_HPP
